
#pragma once

#include "glm\glm.hpp"
#include "glm\ext.hpp"
using namespace glm;


namespace helper
{
	namespace mesh
	{
		Mesh* getAxisMesh()
		{
			VertexAttribDescr vert[2];
			vert[0].attribId = ATTRIB_POSITION;
			vert[0].componentCount = 3;
			vert[0].type = GL_FLOAT;
			vert[0].drawMode = GL_STATIC_DRAW;
			vert[1].attribId = ATTRIB_COLOR;
			vert[1].componentCount = 4;
			vert[1].type = GL_FLOAT;
			vert[1].drawMode = GL_STATIC_DRAW;

			VertexBufferDescr vbDescr;
			vbDescr.vertexAttribsCount = 6;
			vbDescr.vertexAttribsCount = 2;
			vbDescr.vertexDescrPtr = vert;
			vbDescr.vertexCount = 6;

			GLfloat* p = new GLfloat[3 * 6];
			GLfloat* c = new GLfloat[4 * 6];
			p[0]  =   0.0;	p[1]  =   0.0;	p[2]  =   0.0;
			p[3]  = 100.0;	p[4]  =   0.0;	p[5]  =   0.0;
			p[6]  =   0.0;	p[7]  =   0.0;	p[8]  =   0.0;
			p[9]  =   0.0;	p[10] = 100.0;	p[11] =   0.0;
			p[12] =   0.0;	p[13] =   0.0;	p[14] =   0.0;
			p[15] =   0.0;	p[16] =   0.0;	p[17] = 100.0;

			c[0]  = 1.0;	c[1]  = 0.0;	c[2]  = 0.0;	c[3]  = 1.0;
			c[4]  = 1.0;	c[5]  = 0.0;	c[6]  = 0.0;	c[7]  = 1.0;
			c[8]  = 0.0;	c[9]  = 1.0;	c[10] = 0.0;	c[11] = 1.0;
			c[12] = 0.0;	c[13] = 1.0;	c[14] = 0.0;	c[15] = 1.0;
			c[16] = 0.0;	c[17] = 0.0;	c[18] = 1.0;	c[19] = 1.0;
			c[20] = 0.0;	c[21] = 0.0;	c[22] = 1.0;	c[23] = 1.0;

			VertexBuffer* vb = new VertexBuffer(vbDescr);
			vb->setBufferAttribData(ATTRIB_POSITION, p, 6);
			vb->setBufferAttribData(ATTRIB_COLOR, c, 6);

			Mesh* xyzMesh = new Mesh(vb);

			return xyzMesh;
		}
	
		Mesh* getMeshFromFile(const string& filename, ColorRGBA color)
		{
			ifstream file(filename + ".v", ios::in | ios::binary);
			file.seekg(0, ios_base::end);
			long len = (long)file.tellg();
			file.seekg(0, ios_base::beg);
			char* pp = new char[len];
			file.read(pp, len); 
			file.close();

			file.open(filename + ".vn", ios::in | ios::binary);
			file.seekg(0, ios_base::end);
			len = (long)file.tellg();
			file.seekg(0, ios_base::beg);
			char* nn = new char[len];
			file.read(nn, len); 
			file.close();

			int vertexCount = len / (3 * sizeof(float));
	
			float* cc = new float[vertexCount * 4];
			for (int i = 0; i < vertexCount * 4; i+=4) {
				cc[i] = color.r;
				cc[i + 1] = color.g;
				cc[i + 2] = color.b;
				cc[i + 3] = color.a;
			}

			VertexAttribDescr vert3[3];
			vert3[0].attribId = ATTRIB_POSITION;
			vert3[0].componentCount = 3;
			vert3[0].type = GL_FLOAT;
			vert3[0].drawMode = GL_STATIC_DRAW;
			vert3[1].attribId = ATTRIB_COLOR;
			vert3[1].componentCount = 4;
			vert3[1].type = GL_FLOAT;
			vert3[1].drawMode = GL_STATIC_DRAW;
			vert3[2].attribId = ATTRIB_NORMAL;
			vert3[2].componentCount = 3;
			vert3[2].type = GL_FLOAT;
			vert3[2].drawMode = GL_STATIC_DRAW;

			VertexBufferDescr vbDescr3;
			vbDescr3.vertexAttribsCount = 3;
			vbDescr3.vertexDescrPtr = vert3;
			vbDescr3.vertexCount = vertexCount;

			VertexBuffer* vb3 = new VertexBuffer(vbDescr3);

			vb3->setBufferAttribData(ATTRIB_POSITION, pp, vertexCount);
			vb3->setBufferAttribData(ATTRIB_COLOR, cc, vertexCount);
			vb3->setBufferAttribData(ATTRIB_NORMAL, nn, vertexCount);

			Mesh* mesh3 = new Mesh(vb3);

			return mesh3;
		}
	
	}

	namespace texture
	{
		GLuint getEmptyTextureRGBA8(GLuint width, GLuint height)
		{
			GLuint textureId;
			
			glGenTextures(1, &textureId);
			glBindTexture(GL_TEXTURE_2D, textureId);
	
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

			glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
    
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
    
			glBindTexture(GL_TEXTURE_2D, 0);

			return textureId;
		}

		GLuint getDepthTexture(GLuint width, GLuint height)
		{
			GLuint textureId;

			glGenTextures(1, &textureId);
			glBindTexture(GL_TEXTURE_2D, textureId);

			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

			glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);

			glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);

			glBindTexture(GL_TEXTURE_2D, 0);

			return textureId;
		}
	}
}